Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
control.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, NXP Semiconductor
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  * of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  * list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*! \file control.c
32  \brief Defines control sub-system
33 
34  This file contains a UART implementation of the control subsystem. The
35  command interpreter and streaming functions are contained in two separate
36  files. So you can easily swap those out with only minor changes here.
37 */
38 #include "fsl_debug_console.h"
39 #include "board.h"
40 #include "pin_mux.h"
41 #include "fsl_uart.h"
42 #include "fsl_port.h"
43 #include "sensor_fusion.h"
44 #include "control.h"
45 
46 #ifndef F_USE_WIRELESS_UART
47 #define F_USE_WIRELESS_UART 0x0001 ///< 0x0001 to include, 0x0000 otherwise
48 #endif
49 #ifndef F_USE_WIRED_UART
50 #define F_USE_WIRED_UART 0x0002 ///< 0x0002 to include, 0x0000 otherwise
51 #endif
52 
53 #define CONTROL_BAUDRATE 115200 ///< Baudrate to be used for serial communications
54 
55 uart_handle_t wired_uartHandle;
56 uart_handle_t wireless_uartHandle;
57 
58 // global structures
59 uint8_t sUARTOutputBuffer[256]; // larger than the nominal 124 byte size for outgoing packets
60 
61 // direct access to sfg here is the only place in the entire library where we cannot simply
62 // pass a pointer. This is because it is needed by the UART interrupt handlers. Since this
63 // only occurs here, in a subsystem which is defined to be application dependent, that is
64 // considered acceptable.
66 
67 // Blocking function to write a single byte to a specified UART
68 void myUART_WriteByte(UART_Type *base, uint8_t data)
69 {
70  uint8_t flag = 0;
71  while (!flag)
72  {
73  flag = base->S1 & 0x80;
74  }
75  UART_WriteByte(base, data);
76 }
77 
78 // Blocking function pipes specified buffer to both output UARTS
79 int8_t writeControlPort(ControlSubsystem *pComm, uint8_t buffer[], uint16_t nbytes)
80 {
81  uint16_t i;
82  for (i = 0; i < nbytes; i++)
83  {
84 #if F_USE_WIRED_UART
85  myUART_WriteByte(WIRED_UART, buffer[i]);
86 #endif
87 #if F_USE_WIRELESS_UART
88  myUART_WriteByte(WIRELESS_UART, buffer[i]);
89 #endif
90  }
91 
92  return (0);
93 }
94 
95 #if F_USE_WIRELESS_UART
96 // writeWirelessPort() is called from BlueRadios_Init(), which is used to
97 // initialize the Bluetooth module on NXP sensor shields. That function will
98 // obviously need to be replaced for alternate hardware.
99 int8_t writeWirelessPort(uint8_t buffer[], uint16_t nbytes)
100 {
101  uint16_t i;
102  for (i = 0; i < nbytes; i++)
103  {
104  myUART_WriteByte(WIRELESS_UART, buffer[i]);
105  }
106 
107  return (0);
108 }
109 // Wired and Wireless UART interrupt handlers are essentially identical.
111 {
112  uint8_t data;
113  status_t sts;
114  uint32_t nbytes; // number of bytes received
115  uint32_t flags;
116  static char iCommandBuffer_B[5] = "~~~~"; // 5 bytes long to include the unused terminating \0
117  sfg.setStatus(&sfg, RECEIVING_WIRELESS);
118  flags = UART_GetStatusFlags(WIRELESS_UART);
119  /* If new data arrived. */
120  if ((kUART_RxDataRegFullFlag | kUART_RxOverrunFlag) & flags)
121  {
122  sts = UART_TransferGetReceiveCount(WIRELESS_UART, &wireless_uartHandle, &nbytes);
123  if (sts == kStatus_Success)
124  {
125  data = UART_ReadByte(WIRELESS_UART);
126  DecodeCommandBytes(&sfg, iCommandBuffer_B, &data, 1);
127  }
128  }
129 }
130 // initialize BlueRadios BR-LE4.0-D2A Bluetooth module
131 // This is required for NXP FRDM-FXS-MULT2-B boards.
132 void BlueRadios_Init(void)
133 {
134  uint16_t ilen; // command string length
135 
136  // transmit "ATSRM,2,0\r" to minimize traffic from the module
137  // command "ATSRM": sets the module response mode which configures how verbose the module will be
138  // 2: response mode at to minimal
139  // 0: disconnected mode is command mode
140  // \r: carriage return escape sequence
141  strcpy((char *)sUARTOutputBuffer, "ATSRM,2,0\r");
142  ilen = strlen((char *)sUARTOutputBuffer);
144  return;
145 }
146 #endif
147 
148 #if F_USE_WIRED_UART
149 void echo(uint8_t data) // only used for comms debug
150 {
151  /* Send data only when UART TX register is empty and ring buffer has data to send out. */
152  if (kUART_TxDataRegEmptyFlag & UART_GetStatusFlags(WIRED_UART))
153  {
154  UART_WriteByte(WIRED_UART, data);
155  }
156 }
157 // Wired and Wireless UART interrupt handlers are essentially identical.
159 {
160  uint8_t data;
161  status_t sts;
162  uint32_t nbytes; // number of bytes received
163  uint32_t flags;
164  static char iCommandBuffer_A[5] = "~~~~"; // 5 bytes long to include the unused terminating \0
165 
166  sfg.setStatus(&sfg, RECEIVING_WIRED);
167  flags = UART_GetStatusFlags(WIRED_UART);
168  /* If new data arrived. */
169  if ((kUART_RxDataRegFullFlag | kUART_RxOverrunFlag) & flags)
170  {
171  sts = UART_TransferGetReceiveCount(WIRED_UART, &wired_uartHandle, &nbytes);
172  if (sts == kStatus_Success)
173  {
174  data = UART_ReadByte(WIRED_UART);
175  DecodeCommandBytes(&sfg, iCommandBuffer_A, &data, 1);
176  }
177  }
178 }
179 #endif
180 
181 /// Initialize the control subsystem and all related hardware
183  ControlSubsystem *pComm ///< pointer to the control subystem structure
184 )
185 {
186  uart_config_t config;
187  if (pComm)
188  {
189  pComm->DefaultQuaternionPacketType = Q3; // default to simplest algorithm
190  pComm->QuaternionPacketType = Q3; // default to simplest algorithm
191  pComm->AngularVelocityPacketOn = true; // transmit angular velocity packet
192  pComm->DebugPacketOn = true; // transmit debug packet
193  pComm->RPCPacketOn = true; // transmit roll, pitch, compass packet
194  pComm->AltPacketOn = true; // Altitude packet
195  pComm->AccelCalPacketOn = 0;
196  pComm->write = writeControlPort;
197  pComm->stream = CreateAndSendPackets;
198 
199 #if F_USE_WIRED_UART
200  /* Initialize WIRED UART pins below - currently duplicates code in pin_mux.c */
201  CLOCK_EnableClock(WIRED_UART_PORT_CLKEN);
202  PORT_SetPinMux(WIRED_UART_PORT, WIRED_UART_RX_PIN, WIRED_UART_MUX);
203  PORT_SetPinMux(WIRED_UART_PORT, WIRED_UART_TX_PIN, WIRED_UART_MUX);
204  UART_GetDefaultConfig(&config);
205 
206  config.baudRate_Bps = CONTROL_BAUDRATE;
207  config.enableTx = true;
208  config.enableRx = true;
209  config.rxFifoWatermark = 1;
210  UART_Init(WIRED_UART, &config, CLOCK_GetFreq(WIRED_UART_CLKSRC));
211 
212  /* Enable RX interrupt. */
213  UART_EnableInterrupts(WIRED_UART, kUART_RxDataRegFullInterruptEnable |
214  kUART_RxOverrunInterruptEnable);
215  EnableIRQ(WIRED_UART_IRQn);
216 #endif
217 #if F_USE_WIRELESS_UART
218  /* Initialize WIRELESS UART pins below */
219  CLOCK_EnableClock(WIRELESS_UART_PORT_CLKEN);
220  PORT_SetPinMux(WIRELESS_UART_PORT, WIRELESS_UART_RX_PIN,
221  WIRELESS_UART_MUX);
222  PORT_SetPinMux(WIRELESS_UART_PORT, WIRELESS_UART_TX_PIN,
223  WIRELESS_UART_MUX);
224 
225  UART_Init(WIRELESS_UART, &config, CLOCK_GetFreq(WIRELESS_UART_CLKSRC));
226  BlueRadios_Init();
227 
228  /* Enable RX interrupt. */
229  UART_EnableInterrupts(WIRELESS_UART, kUART_RxDataRegFullInterruptEnable |
230  kUART_RxOverrunInterruptEnable);
231  EnableIRQ(WIRELESS_UART_IRQn);
232 #endif
233 
234  return (0);
235  }
236  else
237  {
238  return (1);
239  }
240 }
void WIRED_UART_IRQHandler(void)
Definition: control.c:158
int8_t writeWirelessPort(uint8_t buffer[], uint16_t nbytes)
Definition: control.c:99
Receiving commands over wireless interface (momentary)
volatile uint8_t AltPacketOn
flag to enable altitude packet
Definition: control.h:70
The top level fusion structure.
streamData_t * stream
function to create packets for serial stream
Definition: control.h:73
volatile int8_t AccelCalPacketOn
variable used to coordinate accelerometer calibration
Definition: control.h:71
quaternion_type DefaultQuaternionPacketType
default quaternion transmitted at power on
Definition: control.h:65
uart_handle_t wired_uartHandle
Definition: control.c:55
void myUART_WriteByte(UART_Type *base, uint8_t data)
Definition: control.c:68
int8_t writeControlPort(ControlSubsystem *pComm, uint8_t buffer[], uint16_t nbytes)
Definition: control.c:79
void CreateAndSendPackets(SensorFusionGlobals *sfg, uint8_t *sUARTOutputBuffer)
Called once per fusion cycle to stream information required by the NXP Sensor Fusion Toolbox...
The sensor_fusion.h file implements the top level programming interface.
Receiving commands over wired interface (momentary)
he ControlSubsystem encapsulates command and data streaming functions.
Definition: control.h:64
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:59
volatile uint8_t DebugPacketOn
flag to enable debug packet
Definition: control.h:68
writePort_t * write
low level function to write a char buffer to the serial stream
Definition: control.h:72
int8_t initializeControlPort(ControlSubsystem *pComm)
Initialize the control subsystem and all related hardware.
Definition: control.c:182
void DecodeCommandBytes(SensorFusionGlobals *sfg, char iCommandBuffer[], uint8 sUART_InputBuffer[], uint16 nbytes)
This function is responsible for decoding commands sent by the NXP Sensor Fusion Toolbox and setting ...
void BlueRadios_Init(void)
Used to initialize the Blue Radios Bluetooth module found on the FRDM-FXS-MULT2-B sensor shield from ...
Definition: control.c:132
uart_handle_t wireless_uartHandle
Definition: control.c:56
volatile uint8_t RPCPacketOn
flag to enable roll, pitch, compass packet
Definition: control.h:69
void echo(uint8_t data)
Definition: control.c:149
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
Defines control sub-system.
setStatus_t * setStatus
change status indicator immediately
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
#define CONTROL_BAUDRATE
Baudrate to be used for serial communications.
Definition: control.c:53
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66
void WIRELESS_UART_IRQHandler(void)
Definition: control.c:110
volatile uint8_t AngularVelocityPacketOn
flag to enable angular velocity packet
Definition: control.h:67